//
// Created by abstergo on 2024/2/23.
//

template<typename T>
constexpr T
Optional<T>::value_or(T
&& t)
CONST
	NO_EXCEPT
	{
		return has_value() ? value() : std::forward<T>(t);
	}

template<typename T>
template<class F>
constexpr T
Optional<T>::func_or(F
&& f)
CONST
	NO_EXCEPT
	{
		return has_value() ? value() : f();
	}

template<typename T>
Optional<T>::Optional(const null_opt &nop)
	: _has_value(false) {
}

template<typename T>
Optional<T>::Optional(null_opt &&op)
NO_EXCEPT
: _has_value(false)
{
}

template<typename T>
constexpr Optional<T>
&
Optional<T>::operator=(null_opt &&other)
NO_EXCEPT
{
this->
_has_value = false;
return *this;
}

template<typename T>
constexpr Optional<T>
&
Optional<T>::operator=(const null_opt &other)
NO_EXCEPT
{
this->
_has_value = false;
return *this;
}

template<typename T>
T &Optional<T>::operator*() {
  return _val;
}

template<typename T>
Optional<T>::operator bool()
CONST
{
return
_has_value;
}

template<typename T>
Optional<T>::Optional(Optional && other)
NO_EXCEPT
{
this->
_has_value = other._has_value;
if (other.
has_value()
)
{
this->
_val(other
._val);
}
}

template<typename T>
Optional<T>::Optional(const Optional &other) {
  this->_has_value = other._has_value;
  if (other.has_value()) {
	this->_val(other._val);
  }
}

template<typename T>
constexpr Optional<T>
&
Optional<T>::operator=(const Optional &other) {
  this->_has_value = other._has_value;
  if (other.has_value()) {
	this->_val(other._val);
  }
  return *this;
}

template<typename T>
constexpr Optional<T>
&
Optional<T>::operator=(Optional && other)
NO_EXCEPT
{
this->
_has_value = other._has_value;
if (other.
has_value()
)
{
this->
_val(std::move(other._val)
);
}
return *this;
}

template<typename T>
bool Optional<T>::has_value() const
NO_EXCEPT
{
return
_has_value;
}

template<typename T>
constexpr T
&
Optional<T>::value() & {
  return _val;
}

template<typename T>
constexpr T
&&
Optional<T>::value() && {
  return _val;
}

template<typename T>
constexpr const T
&&
Optional<T>::value() const && {
  return _val;
}

template<typename T>
constexpr const T
&
Optional<T>::value() const & {
  return _val;
}

template<typename T>
Optional<T>::Optional()
	: _has_value(false) {
}

template<typename T>
Optional<T>::Optional(T &&v)
	: _val(std::move(v)), _has_value(true) {
}

template<typename T>
Optional<T>::Optional(const T &v)
	: _val(v), _has_value(true) {
}

template<typename T>
void Optional<T>::reset() {
  _val.~T();
  _has_value = false;
}

template<typename T>
template<class TF>
Optional<TF> Optional<T>::transform(Optional::_transform_function<TF> f) {
  return f(*this);
}

template<typename T>
void Optional<T>::emplace(T &&val) {
  _val(std::forward<T>(val));
  _has_value = true;
}

template<typename T>
void Optional<T>::emplace(const T &val) {
  _val(val);
  _has_value = true;
}
